﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using ZAZ_Demo;

namespace ocmctr
{
    public class UmfCtr
    {
        [DllImport("user32.dll", EntryPoint = "keybd_event")]
        public static extern void keybd_event(
            byte bVk,
            byte bScan,
            int dwFlags,  //0: DOWN, 2: UP  
            int dwExtraInfo  //Default: 0  
        );

        Byte[] ctrlbyte = { 0xff, 0x7, 0x80, 0x69 };
        bool autorun = false;
        Int32 ihdev;
        Int32[] devs;//保存多个设备句柄的数组
        bool isComOpen = false;
        int state = 0;
        Byte sector = 2;//2扇区 卡操作的扇区号
        Byte Address = 8;// sector*4 8块 注意：每个扇区的最后一个块是密码块，比如地址号为3、7、11等是密码块
        int curCardType = 0;
        Byte[] defaultKey = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        Byte[] KeyZero = { 0, 0, 0, 0, 0, 0 };
        Byte[] Key = new Byte[6];
        //Byte[] Key =  { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
        public UmfCtr()
        {
            ctrData();
            devs = new Int32[100];
            for (int i = 0; i < 100; i++)
                devs[i] = 0;
        }
        public UmfCtr(Byte addr, Byte sec)
        {
            ctrData();
            Address = addr;
            sector = sec;
            devs = new Int32[100];
            for (int i = 0; i < 100; i++)
                devs[i] = 0;
        }

        private void ctrData()
        {
            string currentPath = Directory.GetCurrentDirectory();
            string filename = "ctrdata";
            string full = currentPath + "\\" + filename;
            FileStream fs = null;
            string express;
            if (!File.Exists(full))
            {
                throw new Exception("加载密钥失败");
                return;
            }
            else
            {
                fs = new FileStream(full, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            }
            try
            {
                StringBuilder strB = new StringBuilder();
                StreamReader sr = new StreamReader(fs, Encoding.UTF8);
                string line;
                long res;
                while ((line = sr.ReadLine()) != null)
                {
                    strB.Append(line);
                }
                if (strB.Length > 0)
                {
                    express = AESDecrypt(strB.ToString());
                    res = long.Parse(express);
                    Key = ConvertIntToByteArray(res);
                }
                else
                {
                    throw new Exception("加载密钥失败");
                }
            }
            catch (Exception e)
            {
                throw new Exception("加载密钥失败");
            }
        }

        public static string AESDecrypt(string toDecrypt)
        {
            byte[] keyArray = UTF8Encoding.UTF8.GetBytes("zhongweizhilianzhongweizhilian00");
            byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

            RijndaelManaged rDel = new RijndaelManaged();
            rDel.Key = keyArray;
            rDel.Mode = CipherMode.ECB;
            rDel.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rDel.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return UTF8Encoding.UTF8.GetString(resultArray);
        }
        static byte[] ConvertIntToByteArray(Int64 m)
        {
            byte[] arry = new byte[6];
            arry[0] = (byte)(m & 0xFF);
            arry[1] = (byte)((m & 0xFF00) >> 8);
            arry[2] = (byte)((m & 0xFF0000) >> 16);
            arry[3] = (byte)((m >> 24) & 0xFF);
            arry[4] = (byte)((m >> 32) & 0xFF);
            arry[5] = (byte)((m >> 40) & 0xFF);
            return arry;
        }
        public bool isrunning()
        {
            return autorun;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type">发送方式 0:usb 1:串口</param>
        /// <param name="com">串口号:串口方式时必填</param>
        /// <param name="baud">波特率:串口方式时必填</param>
        /// <returns></returns>
        public bool openDev(int type, Int16 com, int baud)
        {
            Byte[] revbuf = new Byte[64];
            /*得到当前连接的设备的句柄*/
            Int32 tmphdev = 0;
            if (type == 0)
            {//USB方式
                int i = 0;
                do
                {
                    tmphdev = Umf.fw_init(100, 0);
                    if (tmphdev > 0)
                    {
                        devs[i] = tmphdev;
                        i++;
                    }

                }
                while (i < 100 && tmphdev > 0);
                ihdev = devs[0];
            }
            else
            {//串口方式
                Int16 fport = com > 0 ? com : (short)1;
                int baudrate = baud > 0 ? baud : 115200;
                ihdev = Umf.fw_init(fport, baudrate);//波特率设为115200
            }

            if (ihdev > 0) isComOpen = true;
            else return false;

            state = Umf.fw_getver(ihdev, ref revbuf[0]);
            if (state != 0) return false;
            else return true;
        }

        public void setCardType(int CardType)
        {
            curCardType = CardType;
        }

        /// <summary>
        /// 关闭所有设备
        /// </summary>
        public void closeDev()
        {
            autorun = false;
            int i = 0;
            while (devs[i] > 0)
            {
                Umf.fw_exit(devs[0]);
                devs[i] = 0;
                i++;
            }

            if (ihdev > 0)
                Umf.fw_exit(ihdev);

            ihdev = 0;
            isComOpen = false;
        }


        //0加载默认密匙 1加载规则密匙
        private int loadKey(int type)
        {
            int state = 0;
            int trynum = 1;
            ulong cardnumber = new ulong();
            while (trynum-- > 0)
            {
                if (type == 0)
                {
                    state = Umf.fw_load_key(ihdev, 0, sector, ref defaultKey[0]);
                    Umf.fw_halt(ihdev);
                    state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
                }
                else if (type == 1)
                {
                    state = Umf.fw_load_key(ihdev, 0, sector, ref Key[0]);
                    Umf.fw_halt(ihdev);
                    state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
                }
                else
                {
                    state = Umf.fw_load_key(ihdev, 0, sector, ref KeyZero[0]);
                    Umf.fw_halt(ihdev);
                    state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
                }
                if (state == 0)
                {
                    state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
                    return 0;
                }
            }
            return -1;
        }

        /// <summary>
        /// 寻卡
        /// </summary>
        /// <returns>0:成功，-1:密码错误，-2:寻卡错误</returns>
        private int findCard(byte sector)
        {
            ulong cardnumber = new ulong();
            switch (curCardType)
            {
                case 0:                              //寻卡验证---M1卡
                case 1:                              //寻卡验证---S70卡
                    {
                        //fw_card
                        loadKey(1);
                        state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
                        if (state != 0)
                        {
                            return -1;
                        }
                        state = Umf.fw_authentication(ihdev, 0, sector);
                        if (state != 0)
                        {
                            loadKey(0);
                            state = Umf.fw_authentication(ihdev, 0, sector);
                            return state;
                        }
                        else
                        {
                            return 0;
                        }
                    }
                case 2:
                    {
                        state = Umf.fw_request_ultralt(ihdev, 1);//1模式寻卡请求
                        state = Umf.fw_anticall_ultralt(ihdev, ref cardnumber);
                        state = Umf.fw_select_ultralt(ihdev, cardnumber);
                        if (state != 0) return -2;//Find Card Error!
                        else return 0;//Find Card Ok!
                    }
                default: return -2;
            }
        }
        private int authCard(ref bool haveWrite)
        {
            loadKey(0);
            state = Umf.fw_authentication(ihdev, 0, sector);
            if (state != 0)
            {
                loadKey(1);
                state = Umf.fw_authentication(ihdev, 0, sector);
                return state;
            }
            else
            {
                haveWrite = true;
                return 0;
            }
        }
        private int authCard()
        {
            loadKey(0);
            state = Umf.fw_authentication(ihdev, 0, sector);
            if (state != 0)
            {
                loadKey(1);
                state = Umf.fw_authentication(ihdev, 0, sector);
                if (state != 0)
                {
                    loadKey(2);
                    state = Umf.fw_authentication(ihdev, 0, sector);
                    return -2;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 读卡
        /// </summary>
        /// <returns>读取成功返回数据 错误返回null</returns>
        public int readCard(ref object data)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        Byte[] revbuf = new Byte[16];
                        StringBuilder r_data = new StringBuilder(300000);

                        state = Umf.fw_read_hex(ihdev, Address, r_data);
                        if (state != 0) return -2;//fw_read 读卡失败

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        data = r_data.ToString();
                        return 0;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3; //Read Page0 Error!

                        //fw_write_ultralt OK!
                        //Read card
                        state = Umf.fw_read_ultralt(ihdev, 4, ref Data[0]);//读第4页的数据
                        if (state != 0) return -4;//fw_read_ultralt Error!
                        else
                        {
                            data = Data;
                            return 0;
                        }//fw_read_ultralt Ok!
                    }
                default: return -5;
            }
        }

        public string getCardNoLoop(ref string _cardno)
        {
            Byte sector = 2;
            ulong cardnumber = new ulong();
            byte[] res = new byte[6];
            long time = DateTime.Now.Ticks;
            bool haveWrite = false;
            state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
            if (state != 0)
            {
                loopcard = 1;
                state = Umf.fw_halt(ihdev);
                return "-1";
            }
            if (loopcard != cardnumber)
            {
                //Console.WriteLine("1,{0}", (DateTime.Now.Ticks - time) / 10000);
                state = authCard(ref haveWrite);
                if (cardnumber != 0)
                {
                    loopcard = cardnumber;
                    string tmp = cardnumber.ToString();
                    _cardno = tmp;
                }
                int i = 0;
                state = Umf.fw_changeb3(ihdev, sector, ref Key[0], ref ctrlbyte[0], 0, ref Key[0]);
                if (state != 0)
                {
                    while (writeKey() != 0 && i++ < 3)
                    {
                        Umf.fw_beep(ihdev, 100);
                    };
                }
                Umf.fw_card(ihdev, 0x31, ref cardnumber);
                authCard(ref haveWrite);
                i = 0;
                StringBuilder r_data = new StringBuilder();
                state = Umf.fw_read_hex(ihdev, Address, r_data);
                if (state != 0) return "-4";
                string rtmp = r_data.Length>32?r_data.ToString().Substring(0, 32):"";
                if (!rtmp.Equals("6F636D00000000000000000000000000") && rtmp.IndexOf("222222222222222222222222") < 0 && rtmp.IndexOf("333333333333333333333333") < 0)
                {
                    state = Umf.fw_write_hex(ihdev, Address, "6F636D000000000000000000000000AB");
                    if (state != 0)
                    {
                        while (writeCard("6F636D000000000000000000000000AB") != 0 && i++ < 5)
                        {
                            Umf.fw_beep(ihdev, 100);
                        };
                        //return "-3";
                    }
                }
                Umf.fw_beep(ihdev, 20);
                state = Umf.fw_halt(ihdev);
            }
            return "0";
        }

        public void startRead()
        {
            autorun = true;
            new Thread(new ThreadStart(startReadThread)).Start();
        }
        public void stopRead()
        {
            autorun = false;
        }

        string oldtmp = "1";
        private void startReadThread()
        {
            //while (autorun)
            //{
            //    getCardNoLoop();
            //    Thread.Sleep(300);
            //}
            Thread.Sleep(200);
            string _cardno = "";
            string res = "";
            while (autorun)
            {
                res = getCardNoLoop(ref _cardno);
                if (!_cardno.Equals(""))
                {
                    while (_cardno.Length < 10) _cardno = "0" + _cardno;
                    sendKey(_cardno);
                }
                _cardno = "";
            }
        }

        ulong loopcard = 0;
        public int getCardNoLoop()
        {
            Byte sector = 2;
            ulong cardnumber = new ulong();
            byte[] res = new byte[6];
            long time = DateTime.Now.Ticks;
            state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
            if (state != 0)
            {
                loopcard = 1;
                state = Umf.fw_halt(ihdev);
                return -1;
            }
            if (loopcard != cardnumber)
            {
                //Console.WriteLine("1,{0}", (DateTime.Now.Ticks - time) / 10000);
                state = authCard();
                if (state != 0)
                {
                    Umf.fw_beep(ihdev, 20);
                    Thread.Sleep(20);
                    Umf.fw_beep(ihdev, 20);
                    Umf.fw_halt(ihdev);
                    return -2;
                }
                StringBuilder r_data = new StringBuilder(300);
                state = Umf.fw_read_hex(ihdev, Address, r_data);
                if (state != 0) return -4;
                string rtmp = r_data.ToString().Substring(0, 32);
                int ii = rtmp.IndexOf("222222222222222222222222");
                if (!rtmp.Equals("6F636D00000000000000000000000000") && rtmp.IndexOf("222222222222222222222222") < 0 && rtmp.IndexOf("333333333333333333333333") < 0)
                {

                    state = Umf.fw_write_hex(ihdev, Address, "6F636D000000000000000000000000AB");
                    if (state != 0) return -3;
                }
                state = Umf.fw_changeb3(ihdev, sector, ref Key[0], ref ctrlbyte[0], 0, ref Key[0]);
                if (state != 0) return -5;
                loopcard = cardnumber;
                Umf.fw_beep(ihdev, 6);
                //Console.WriteLine("7,{0}", (DateTime.Now.Ticks - time) / 10000);
                if (cardnumber != 0)
                {
                    string tmp = cardnumber.ToString();
                    while (tmp.Length < 10)
                    {
                        tmp = "0" + tmp;
                    }
                    sendKey(tmp);
                }
                //Console.WriteLine("8,{0}", (DateTime.Now.Ticks - time) / 10000);
                state = Umf.fw_halt(ihdev);
            }
            //fw_halt
            return 0;
        }
        /// <summary>
        /// 读卡
        /// </summary>
        /// <returns>读取成功返回数据 错误返回null</returns>
        public int readCard(ref object data, Byte addr)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函 数（读写）----S70卡
                    {
                        Byte[] revbuf = new Byte[16];
                        StringBuilder r_data = new StringBuilder(300000);
                        state = Umf.fw_read_hex(ihdev, addr, r_data);
                        if (state != 0) return -4;//fw_read 读卡失败

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        data = r_data.ToString();
                        return 0;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3; //Read Page0 Error!

                        //fw_write_ultralt OK!
                        //Read card
                        state = Umf.fw_read_ultralt(ihdev, 4, ref Data[0]);//读第4页的数据
                        if (state != 0) return -4;//fw_read_ultralt Error!
                        else
                        {
                            data = Data;
                            return 0;
                        }//fw_read_ultralt Ok!
                    }
                default: return -5;
            }
        }

        public int writeCard(string w_data, Byte addr)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        state = changeKey();
                        if (state == 0) st = 0;
                        else return -5;
                        state = Umf.fw_write_hex(ihdev, addr, w_data);

                        if (state == 0) st = 0;
                        else st = -3;

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                default: return -2;
            }
        }
        private static long GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds);
        }
        public static string dexStrtoHexStr(string dex)
        {
            int enter = 0;
            int.TryParse(dex, out enter);
            StringBuilder sb = new StringBuilder(enter.ToString("X2"));
            for (int i = sb.Length; i < 8; ++i)
            {
                sb.Insert(0, "0");
            }
            string strSb = sb.ToString();
            char[] result = new char[8];
            result[0] = strSb[6];
            result[1] = strSb[7];
            result[2] = strSb[4];
            result[3] = strSb[5];
            result[4] = strSb[2];
            result[5] = strSb[3];
            result[6] = strSb[0];
            result[7] = strSb[1];
            return new string(result);
        }

        private void sendKey(string data)
        {
            //data = StrReverseToDex(data);
            for (int i = 0; i < data.Length; ++i)
            {
                byte tmp = (byte)data[i];
                keybd_event(Convert.ToByte(tmp), 0, 0, 0);
                Thread.Sleep(15);
            }
        }


        private string StrReverseToDex(string strSb)
        {
            char[] result = new char[8];
            result[0] = strSb[6];
            result[1] = strSb[7];
            result[2] = strSb[4];
            result[3] = strSb[5];
            result[4] = strSb[2];
            result[5] = strSb[3];
            result[6] = strSb[0];
            result[7] = strSb[1];
            StringBuilder temp = new StringBuilder(Convert.ToInt64(new string(result), 16) + "");
            for (int i = temp.Length; i < 10; i++)
            {
                temp.Insert(0, "0");
            }
            return temp.ToString();
        }

        public int getCardNo(ref object data)
        {
            Byte sector = 0;
            ulong cardnumber = new ulong();
            byte[] res = new byte[6];
            state = Umf.fw_card(ihdev, 0x31, ref cardnumber);
            if (state != 0) return -1;
            else
            {
                res = ConvertIntToByteArray((int)cardnumber);
                data = BitConverter.ToString(res).Replace("-", "").Substring(0, 8);
                return 0;
            }
        }

        private int changeKey()
        {
            Byte[] keya = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
            Byte[] ctrlbyte = { 0xff, 0x7, 0x80, 0x69 };
            Byte[] keyb = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
            //fw_change3
            state = findCard(sector);
            state = Umf.fw_changeb3(ihdev, sector, ref Key[0], ref ctrlbyte[0], 0, ref Key[0]);
            if (state == 0) return 0;
            return -5;
        }

        public int writeKey()
        {
            state = changeKey();
            return state;
        }

        /// <summary>
        /// 写卡
        /// </summary>
        /// <param name="w_data">16进制字符串</param>
        /// <returns></returns>
        public int writeCard(string w_data)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        StringBuilder r_data = new StringBuilder(300000);

                        //fw_write
                        // state = fw_write(ihdev, Address, ref sendbuf[0]);
                        state = changeKey();
                        if (state == 0) st = 0;
                        else return state;
                        state = Umf.fw_write_hex(ihdev, Address, w_data);

                        if (state == 0) st = 0;
                        else st = -3;

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3;

                        //写卡
                        char[] chars = w_data.ToCharArray();
                        byte[] newCardData = Encoding.Unicode.GetBytes(chars);

                        state = Umf.fw_write_ultralt(ihdev, 4, ref newCardData[0]);//写第4页

                        if (state != 0) return -2;
                        else return 0;
                    }
                default: return -2;
            }
        }

        public int readCupNo(ref object data)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        Byte[] revbuf = new Byte[16];
                        StringBuilder r_data = new StringBuilder(300000);

                        state = Umf.fw_read_hex(ihdev, 9, r_data);
                        if (state != 0) return -4;//fw_read 读卡失败

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        data = r_data.ToString().Substring(6, 8);
                        return 0;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3; //Read Page0 Error!

                        //fw_write_ultralt OK!
                        //Read card
                        state = Umf.fw_read_ultralt(ihdev, 4, ref Data[0]);//读第4页的数据
                        if (state != 0) return -4;//fw_read_ultralt Error!
                        else
                        {
                            data = Data;
                            return 0;
                        }//fw_read_ultralt Ok!
                    }
                default: return -5;
            }
        }

        public int readAuth(ref object data)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        Byte[] revbuf = new Byte[16];
                        StringBuilder r_data = new StringBuilder(300000);

                        state = Umf.fw_read_hex(ihdev, 10, r_data);
                        if (state != 0) return -4;//fw_read 读卡失败

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        data = r_data.ToString();
                        return 0;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3; //Read Page0 Error!

                        //fw_write_ultralt OK!
                        //Read card
                        state = Umf.fw_read_ultralt(ihdev, 4, ref Data[0]);//读第4页的数据
                        if (state != 0) return -4;//fw_read_ultralt Error!
                        else
                        {
                            data = Data;
                            return 0;
                        }//fw_read_ultralt Ok!
                    }
                default: return -5;
            }
        }
        public int writeAuth(string w_data)
        {
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        StringBuilder r_data = new StringBuilder(300000);

                        state = changeKey();
                        if (state == 0) st = 0;
                        else return -5;
                        state = Umf.fw_write_hex(ihdev, 10, w_data);

                        if (state == 0) st = 0;
                        else st = -3;

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                case 2:
                    {
                        //读写卡操作之前，先读一下第0块
                        byte[] Data = new byte[6];
                        state = Umf.fw_read_ultralt(ihdev, 0, ref Data[0]);//读第0页
                        if (state != 0) return -3;

                        //写卡
                        char[] chars = w_data.ToCharArray();
                        byte[] newCardData = Encoding.Unicode.GetBytes(chars);

                        state = Umf.fw_write_ultralt(ihdev, 4, ref newCardData[0]);//写第4页

                        if (state != 0) return -2;
                        else return 0;
                    }
                default: return -2;
            }
        }
        public int writeCard(byte[] databuff)
        {
            byte[] datatmp = databuff;
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        StringBuilder r_data = new StringBuilder(300000);
                        state = changeKey();
                        if (state == 0) st = 0;
                        else return -5;
                        //fw_write
                        state = Umf.fw_write(ihdev, Address, ref datatmp[0]);

                        if (state == 0) st = 0;
                        else st = -3;

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                default: return -2;
            }
        }

        public int bee(UInt32 ms)
        {
            return Umf.fw_beep(ihdev, ms);
        }

        public int NewFuc()
        {
            return 1;
        }

        public int disableCup()
        {
            StringBuilder d_data = new StringBuilder(300000);
            byte addr = 9;
            state = findCard(sector);
            if (state != 0) return state;
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        StringBuilder r_data = new StringBuilder(300000);

                        //fw_write
                        //state = Umf.fw_write_hex(ihdev, addr, "6F636D03090909000000000000000000");
                        state = Umf.fw_write_hex(ihdev, addr, "6F636D02000000000000000000000000");

                        if (state == 0) st = 0;
                        else st = -3;

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                default: return -2;
            }
        }

        //private void test() { }

        public int clearCup()
        {
            byte[] buff = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
            byte addr = 9;
            state = findCard(sector);
            if (state != 0)
            {
                Umf.fw_beep(ihdev, 20);
                return state;
            }
            switch (curCardType)
            {
                case 0:                               //卡函数（读写）----M1卡
                case 1:                               //卡函数（读写）----S70卡
                    {
                        int st = -1;
                        StringBuilder r_data = new StringBuilder(300000);

                        //fw_write
                        state = Umf.fw_write(ihdev, addr, ref buff[0]);

                        if (state == 0) st = 0;
                        else
                        {
                            Umf.fw_beep(ihdev, 20);
                            Thread.Sleep(20);
                            Umf.fw_beep(ihdev, 20);
                            st = -3;
                        }

                        //fw_halt
                        state = Umf.fw_halt(ihdev);
                        return st;
                    }
                default: return -2;
            }
        }

    }

    public class FingerCtr
    {
        IntPtr hHandle = new IntPtr();
        UInt32 nDevAddr = 0xffffffff;
        bool isusb = true;
        int m_baud = 57600;
        int m_com = 0;
        int m_Fpid = 0;
        int IMAGE_SIZE = (256 * 288);

        private string getFpdb()
        {
            int ret = 0;
            uint nDevAddr = 0xffffffff;
            byte[] indextable = new byte[32];

            string tmp = "";
            int temp, ttt;
            for (int moban = 0; moban < 4; moban++)
            {
                ret = Fingerdll.ZAZReadIndexTable(hHandle, nDevAddr, moban, ref indextable[0]);
                if (ret == 0)
                {
                    for (int ari = 0; ari < 32; ari++)
                    {
                        for (int i = 0; i < 8; i++)
                        {
                            temp = indextable[ari];
                            ttt = (0x01 << i);
                            temp &= ttt;
                            if (temp != 0)
                            {
                                int m_Addr;
                                m_Addr = moban * 32 * 8 + ari * 8 + i;
                                tmp += m_Addr.ToString() + ",";
                            }
                        }
                    }
                }
                else
                {
                    return Fingerdll.ZAZErr2Str(ret);
                }
            }
            return tmp;
        }


        private int upImg(byte[] ImgData, ref int ImgLen)
        {
            return Fingerdll.ZAZUpImage(hHandle, nDevAddr, ImgData, ref ImgLen);
        }

        /// <summary>
        /// 在窗体上显示指纹图像
        /// </summary>
        /// <returns></returns>
        private int showImg(IntPtr hWnd, ref byte ImgData)
        {
            return Fingerdll.ZAZShowFingerData(hWnd, ref ImgData);
        }
        private int getImg()
        {
            return Fingerdll.ZAZGetImage(hHandle, nDevAddr);
        }
        /// <summary>
        /// 生成指纹模板
        /// </summary>
        /// <param name="iBuffer"></param>
        /// <returns></returns>
        private int genChar(int iBuffer)
        {
            return Fingerdll.ZAZGenChar(hHandle, nDevAddr, iBuffer);
        }


        public int openDev()
        {
            int ret = 0;
            int devce_usb = 0;
            uint nDevAddr = 0xffffffff;

            //  Fingerdll.ZAZCloseDeviceEx(hHandle);
            ret = connect_usb();
            if (ret != 0)
            { connect_close(); return -1; }
            isusb = true;
            connect_close();
            return 0;
        }

        public void closeDev()
        {
            Fingerdll.ZAZCloseDeviceEx(hHandle);
        }

        public int connect_usb()
        {
            int ret = 0;
            int devce_usb = 0;
            byte[] iPwd = new byte[4];
            uint nDevAddr = 0xffffffff;

            ret = Fingerdll.ZAZOpenDeviceEx(ref hHandle, 2, 0, 0, 2, 0);
            if (ret == 0)
            {
                devce_usb = 2;  //无驱
            }
            if (devce_usb == 1)
            {
                if (Fingerdll.ZAZVfyPwd(hHandle, nDevAddr, ref iPwd[0]) == 0) return 0;
                else return -1;
            }
            else if (devce_usb == 2) return 0;
            else return -1;//打开USB设备失败,请查看设备是否连接 usb设备请查看“设备管理器”
        }

        public void connect_close()
        {
            Fingerdll.ZAZCloseDeviceEx(hHandle);
        }

        public int upChar(ref byte[] ptemp, ref int ptempLen)
        {
            int ret = -1;
            ret = Fingerdll.ZAZRegModule(hHandle, nDevAddr);
            if (ret == 0) return Fingerdll.ZAZUpChar(hHandle, nDevAddr, 1, ref ptemp[0], ref ptempLen);
            else return ret;
        }


        /// <summary>
        /// 精确比对
        /// </summary>
        /// <param name="nScore"></param>
        /// <returns></returns>
        public int match(byte[] ptemp)
        {
            int nScore = 0;
            int ret = 0;
            byte[] temp = ptemp;
            int len = 0;
            ret = Fingerdll.ZAZDownChar(hHandle, nDevAddr, 2, ref temp[0], ref len);
            if (ret == 0)
            {
                return Fingerdll.ZAZMatch(hHandle, nDevAddr, ref nScore);
            }
            else return ret;

        }

        /// <summary>
        /// 合成模板
        /// </summary>
        /// <returns></returns>
        bool rolling = false;

        public void stoproll()
        {
            rolling = false;
        }
        public int getchar(int buffer, int timeout)
        {
            int ret = 0;
            int ImgLen = 0;
            int iBuffer = buffer;
            int _timeout = timeout / 100;   //定义等待超时
            rolling = true;
        /****************获取图像*********/
        BEIG1:
            if (!rolling) return 33;
            ret = getImg();  //获取图象 
            if (ret == 2)
            { //放上手指 
            }
            else if (ret == 0)
            {
                //获取图像成功
            }
            else { return ret; }
            if (ret == 2)
            { //超时判断
                if (timeout < 0) return 0;
                timeout--;
                Thread.Sleep(10); goto BEIG1;
            }
            if (ret != 0) return 0;

            //////////////////////////////////////////////////////////////////////////
            /****************生成特征 *********/

            ret = genChar(iBuffer);  //生成模板
            if (ret != 0)
            { return 0; }
            else
            { //生成指纹特征 + buffer.ToString());
            }
            Thread.Sleep(10);
        BEIG2:
            if (!rolling) return 33;
            if (ret == 0)
            { //超时判断
                ret = getImg();  //获取图象 
                //等待手指拿开
                goto BEIG2;
            }
            if (ret == 1) return 0;
            return 1;
        }

        public int getchar(int buffer, int timeout, IntPtr hWnd, ref byte[] ImgData)
        {
            int ret = 0;
            int ImgLen = 0;
            int iBuffer = buffer;
            int _timeout = timeout / 100;   //定义等待超时
            rolling = true;
        /****************获取图像*********/
        BEIG1:
            if (!rolling) return 33;
            ret = getImg();  //获取图象 
            if (ret == 2)
            { //放上手指 
            }
            else if (ret == 0)
            {
                //获取图像成功
            }
            else { return ret; }
            if (ret == 2)
            { //超时判断
                if (timeout < 0) return 0;
                timeout--;
                Console.WriteLine("timeout" + timeout);
                Thread.Sleep(10); goto BEIG1;
            }
            if (ret != 0) return 0;
            //////////////////////////////////////////////////////////////////////////
            //不涉及图像，下面可以省略
            /****************上传图像*********/
            //正在上传图像请等待
            ret = upImg(ImgData, ref ImgLen);  //上传图象
            if (ret != 0)
            { return ret; }
            ret = showImg(hWnd, ref ImgData[0]);

            //////////////////////////////////////////////////////////////////////////
            /****************生成特征 *********/

            ret = genChar(iBuffer);  //生成模板
            if (ret != 0)
            { return 0; }
            else
            { //生成指纹特征 + buffer.ToString());
            }
            Thread.Sleep(10);
        BEIG2:
            if (!rolling) return 33;
            if (ret == 0)
            { //超时判断
                ret = getImg();  //获取图象 
                //等待手指拿开
            }
            if (ret == 1) return 0;
            return 1;
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        /// <param name="ret"></param>
        /// <returns></returns>
        public string getError(int ret)
        {
            switch (ret)
            {
                case 1: return "数据包接收错误";
                case 2: return "传感器上没有手指";
                case 3: return "录入指纹图象失败";
                case 4: return "指纹太淡";
                case 5: return "指纹太糊";
                case 6: return "指纹太乱";
                case 7: return "指纹特征点太少";
                case 8: return "指纹不匹配";
                case 9: return "没搜索到指纹";
                case 10: return "特征合并失败";
                case 11: return "地址号超出指纹库范围";
                case 12: return "从指纹库读模板出错";
                case 13: return "上传特征失败";
                case 14: return "模块不能接收后续数据包";
                case 15: return "上传图象失败";
                case 16: return "删除模板失败";
                case 17: return "清空指纹库失败";
                case 18: return "不能进入休眠";
                case 19: return "口令不正确";
                case 20: return "系统复位失败";
                case 21: return "无效指纹图象";
                case 22: return "在线升级失败";
                case 23: return "残留或未移动";
                case 24: return "表示读写FLASH出错";
                case 25: return "未定义错误";
                case 26: return "无效寄存器号";
                case 27: return "寄存器设定内容错误号";
                case 28: return "记事本页码指定错误";
                case 29: return "端口操作失败";
                case 30: return "自动注册（enroll）失败";
                case 31: return "指纹库满";
                case 32: return "空操作";
                case 33: return "主动关闭";
                default:
                    return "未知错误";
            }
        }

    }
}
